#include "StdAfx.h"
#include "Condition.h"

#include <Mmsystem.h>
#include <Windows.h>
#pragma comment(lib, "winmm.lib")


inline void ten_bit(int& num , int i)
{
	if ( i >= 10 && i < 20 ) num = 1 ;
	else if ( i >= 20 && i < 30 ) num = 2 ;
	else if ( i >= 30 && i < 40 ) num = 3 ;
	else if ( i >= 40 && i < 50 ) num = 4 ;
	else if ( i >= 50 && i < 60 ) num = 5 ;
	else if ( i >= 60 && i < 70 ) num = 6 ;
	else if ( i >= 70 && i < 80 ) num = 7 ;
	else if ( i >= 80 && i < 90 ) num = 8 ;
	else if ( i >= 90 && i < 100 ) num = 9 ;
	else
		num = 0 ;
}

inline void hundred_bit(int& num ,int i)
{
	if ( i >= 100 && i < 200 ) num = 1 ;
	else if ( i >= 200 && i < 300 ) num = 2 ;
	else if ( i >= 300 && i < 400 ) num = 3 ;
	else if ( i >= 400 && i < 500 ) num = 4 ;
	else if ( i >= 500 && i < 600 ) num = 5 ;
	else if ( i >= 600 && i < 700 ) num = 6 ;
	else if ( i >= 700 && i < 800 ) num = 7 ;
	else if ( i >= 800 && i < 900 ) num = 8 ;
	else if ( i >= 900 && i < 1000 ) num = 9 ;
	else
		num = 0 ;
}

inline void thousand_bit(int& num,int i)
{
	if ( i >= 1000 && i < 2000 ) num = 1 ;
	else if ( i >= 2000 && i < 3000 ) num = 2 ;
	else if ( i >= 3000 && i < 4000 ) num = 3 ;
	else if ( i >= 4000 && i < 5000 ) num = 4 ;
	else if ( i >= 5000 && i < 6000 ) num = 5 ;
	else if ( i >= 6000 && i < 7000 ) num = 6 ;
	else if ( i >= 7000 && i < 8000 ) num = 7 ;
	else if ( i >= 8000 && i < 9000 ) num = 8 ;
	else if ( i >= 9000 && i < 10000 ) num = 9 ;
	else
		num = 0 ;
}

inline void ten_thousand_bit(int& num,int i)
{
	if ( i >= 10000 && i < 20000 ) num = 1 ;
	else if ( i >= 20000 && i < 30000 ) num = 2 ;
	else if ( i >= 30000 && i < 40000 ) num = 3 ;
	else if ( i >= 40000 && i < 50000 ) num = 4 ;
	else if ( i >= 50000 && i < 60000 ) num = 5 ;
	else if ( i >= 60000 && i < 70000 ) num = 6 ;
	else if ( i >= 70000 && i < 80000 ) num = 7 ;
	else if ( i >= 80000 && i < 90000 ) num = 8 ;
	else if ( i >= 90000 && i < 100000 ) num = 9 ;
	else
		num = 0 ;
}

inline void process_2_bit(EveryGroup& g,int i)
{
	g.num[0] = g.num[1] = g.num[2] = 0 ;
	g.num[4] = i % 10 ;
	ten_bit(g.num[3],i) ;
}

inline void process_3_bit(EveryGroup& g,int i)
{
	g.num[0] = g.num[1] = 0 ;g.num[4] = i % 10 ;
	hundred_bit(g.num[2],i) ;
	ten_bit(g.num[3],i%100) ;
}

inline void process_4_bit(EveryGroup& g ,int i)
{
	g.num[0] = 0 ;g.num[4] = i % 10 ;
	thousand_bit(g.num[1],i) ;
	int temp = i%1000 ;
	hundred_bit(g.num[2],temp) ;
	ten_bit(g.num[3],temp%100) ;
}

inline void process_5_bit(EveryGroup& g,int i)
{
	ten_thousand_bit(g.num[0],i) ;
	int temp = i % 10000 ;
	thousand_bit(g.num[1],temp) ;
	temp = temp % 1000 ;
	hundred_bit(g.num[2],temp) ;
	temp = temp % 100 ;
	ten_bit(g.num[3],temp) ;
	g.num[4] = i % 10 ;
}

CCondition::CCondition(void)
{
	Classify() ;
}

CCondition::~CCondition(void)
{
	m_vecFull.clear() ;
	m_vecFiveNum.clear() ;
	m_vecFourNum.clear() ;
	m_vecThreeNum.clear() ;
	m_vecTwoNum.clear() ;
	m_vecOneNum.clear() ;
}

void CCondition::Classify()
{
	init() ;

	typedef std::map<int,int>::value_type VAL ;
	EveryGroup _group ;
	DWORD begn = timeGetTime() ;

	int one_num_idx = 0 ;
	int two_num_idx = 0 ;
	int three_num_idx = 0 ;
	int four_num_idx = 0 ;
	int five_num_idx = 0 ;
	for ( int i = 0 ; i < 100000 ; i++ )
	{
		if ( i < 10 )
		{
			_group.num[0] = _group.num[1] = _group.num[2] = _group.num[3] = 0 ;
			_group.num[4] = i ;
		}
		else if ( i < 100 ) process_2_bit(_group,i) ;
		else if ( i < 1000 ) process_3_bit(_group,i) ;
		else if ( i < 10000 ) process_4_bit(_group,i) ;
		else process_5_bit(_group,i) ;
		m_vecFull[i] = _group ;
		
		_group.number.clear() ;
		for(int j = 0 ; j < 5 ; j++) _group.number.insert(VAL(_group.num[j],_group.num[j])) ;
		if (_group.number.size() == 1) 
		{
			m_vecOneNum[one_num_idx] = _group ;
			one_num_idx++ ;
		}
		else if (_group.number.size() == 2)
		{
			m_vecTwoNum[two_num_idx] = _group ;
			two_num_idx++ ;
		}
		else if (_group.number.size() == 3)
		{
			m_vecThreeNum[three_num_idx] = _group ;
			three_num_idx++ ;
		}
		else if (_group.number.size() == 4)
		{
			m_vecFourNum[four_num_idx] = _group ;
			four_num_idx++ ;
		}
		else if (_group.number.size() == 5)
		{
			m_vecFiveNum[five_num_idx] = _group ;
			five_num_idx++ ;
		}
	}

	DWORD last = timeGetTime()-begn ;
	
}

CCondition* CCondition::getSingleton()
{
	static CCondition instance__ ;
	return &instance__ ;
}

void CCondition::init()
{
	m_vecFull.resize(100000) ;
	m_vecFiveNum.resize(30240) ;
	m_vecFourNum.resize(50400) ;
	m_vecThreeNum.resize(18000) ;
	m_vecTwoNum.resize(1350) ;
	m_vecOneNum.resize(10) ;

	//m_vecOneRepeat.resize(7200) ;
	m_vecOneRepeat.clear() ;
	//m_vecTwoRepeat.resize(10800) ;
	m_vecTwoRepeat.clear() ;
}

VEC_GROUP& CCondition::getOneRepeat()
{
	if ( !m_vecOneRepeat.empty() ) return m_vecOneRepeat ;

	check_repeat_in_three_num() ;

	return m_vecOneRepeat ;
}

VEC_GROUP& CCondition::getTwoRepeat()
{
	if ( !m_vecTwoRepeat.empty() ) return m_vecTwoRepeat ;

	check_repeat_in_three_num() ;

	return m_vecTwoRepeat ;
}

void CCondition::check_repeat_in_three_num()
{
	m_vecOneRepeat.resize(7200) ;
	m_vecTwoRepeat.resize(10800) ;
	int one_rep = 0 ;
	int two_rep = 0 ;
	#pragma omp parallel for
	for ( int i = 0 ; i < 18000 ; i++ )
	{
		int cnt1 = 0,cnt2=0,cnt3=0 ;
		std::map<int,int>::iterator it = m_vecThreeNum[i].number.begin() ;
		for(int idx = 0 ; idx < 5 ; idx++)
		{
			if (it->first == m_vecThreeNum[i].num[idx]) cnt1++ ;
		}
		it++ ;
		for(int idx = 0 ; idx < 5 ; idx++)
		{
			if (it->first == m_vecThreeNum[i].num[idx]) cnt2++ ;
		}
		it++ ;
		for(int idx = 0 ; idx < 5 ; idx++)
		{
			if (it->first == m_vecThreeNum[i].num[idx]) cnt3++ ;
		}
		if ( cnt1 == 3 || cnt2 == 3 || cnt3 == 3 )
		{
			//m_vecOneRepeat.push_back(_group) ;
			m_vecOneRepeat[one_rep] = m_vecThreeNum[i] ;
			one_rep++ ;
		}
		else
		{
			//m_vecTwoRepeat.push_back(_group) ;
			m_vecTwoRepeat[two_rep] = m_vecThreeNum[i] ;
			two_rep++ ;
		}
	}
}